package org.team4u.ic

import com.asiainfo.common.util.FileUtil
import com.asiainfo.common.util.ThreadUtil
import com.asiainfo.common.util.config.Configs
import com.asiainfo.common.util.log.Logs
import org.nutz.img.Images
import org.nutz.lang.Stopwatch
import java.io.File
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern

/**
 * @author Jay Wu
 */
object ImageCompressor {

    private val log = Logs.get()

    private val SELF_ADAPTION = -1
    private val SCALA_MODE_PERCENTAGE = 0

    fun compress(compressConfig: CompressConfig) {
        val pool = ThreadUtil.newBlockingFixedThreadPool(compressConfig.threadCount)
        var count = 0
        val sw = Stopwatch.begin()

        val targetDirFile = File(compressConfig.targetDir)
        FileUtil.deleteDir(targetDirFile)
        FileUtil.createDirIfNoExists(targetDirFile)

        FileUtil.ls(FileUtil.checkFile(compressConfig.sourceDir),
                Pattern.compile(compressConfig.fileRegex, Pattern.CASE_INSENSITIVE), false,
                FileUtil.LsMode.FILE)?.forEach { sourceFile ->
            if (sourceFile.isHidden) {
                return@forEach
            }

            pool.execute {
                val sourceBufferedImage = Images.read(sourceFile)

                log.infof("Image compressing(file=%s,width=%s,height=%s,size=%skb)",
                        sourceFile.absolutePath,
                        sourceBufferedImage.width, sourceBufferedImage.height,
                        sourceFile.length() / 1024)

                var width: Int = 0
                var height: Int = 0

                // 百分比模式
                if (compressConfig.scalaMode == SCALA_MODE_PERCENTAGE) {
                    width = if (compressConfig.width == SELF_ADAPTION) {
                        SELF_ADAPTION
                    } else {
                        sourceBufferedImage.width * compressConfig.width / 100
                    }

                    height = if (compressConfig.height == SELF_ADAPTION) {
                        SELF_ADAPTION
                    } else {
                        sourceBufferedImage.width * compressConfig.height / 100
                    }
                }

                val targetBufferedImage = Images.scale(sourceBufferedImage, width, height)
                val targetFile = File(targetDirFile.absolutePath + File.separator + sourceFile.name)

                if (isJpegFile(sourceFile)) {
                    Images.writeJpeg(targetBufferedImage, targetFile, compressConfig.quality / 100f)
                } else {
                    Images.write(targetBufferedImage, targetFile)
                }

                log.infof("Image compressed(index=%s,file=%s,width=%s,height=%s,size=%skb)",
                        ++count, targetFile,
                        targetBufferedImage.width, targetBufferedImage.height,
                        targetFile.length() / 1024)
            }
        }

        pool.shutdown()
        pool.awaitTermination(1, TimeUnit.DAYS)

        sw.stop()
        log.infof("All images compressed(count=%s,timeSpend=%ss)", count, sw.duration / 1000)
    }

    private fun isJpegFile(file: File): Boolean {
        val suffix = FileUtil.getSuffix(file)
        return suffix.equals(".jpg", true) || suffix.equals(".jpeg", true)
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val compressConfig = Configs.getInstance().getOrLoadWithFilePath(
                CompressConfig::class.java,
                "application.js"
        )

        ImageCompressor.compress(compressConfig)
    }
}